{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VPoser poZ Space for Body Models\n",
    "The original body pose space of [SMPL](http://smpl.is.tue.mpg.de/) and [SMPL-X](https://smpl-x.is.tue.mpg.de/) \n",
    "(jointly refered here as SMPL) are not bounded to natural human pose space. That means you can put a vector value \n",
    "as the pose of a SMPL body model and get broken body, that might not even look like a human.\n",
    "To address this you can replace the original pose space of SMPL with VPoser's latent space that corresponds to natural human pose space.\n",
    "This means if you sample a 32 dimentional random vector from a Normal distribution and pass it as your pose you should get  a viable human joint configuration. This representation of pose is fully differentiable and can be used in an end-to-end deep learning pipeline.\n",
    "\n",
    "An example use case is an expressive 2D-to-3D lifting of a human image done in [Expressive Body Capture:\n",
    "3D Hands, Face, and Body from a Single Image](https://smpl-x.is.tue.mpg.de/)\n",
    " \n",
    "To load a SMPL with this body pose representation first you need to obtain a trained VPoser and a variation of SMPL model, here we use SMPLx, from https://smpl-x.is.tue.mpg.de/downloads .\n",
    "Put the obtained vposer model and body models in a folder, here we assume respectively\n",
    "\n",
    "'GITHUB_CLONE_ROOT/human_body_prior/dowloads/vposer_v1_0', and \n",
    "'GITHUB_CLONE_ROOT/human_body_prior/dowloads/models'\n",
    "\n",
    "and afterwards you can use the following code snippet to load BodyModel with vposer: \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "%matplotlib notebook\n",
    "%matplotlib inline\n",
    "\n",
    "expr_dir = '../downloads/vposer_v1_0' #'TRAINED_MODEL_DIRECTORY'  in this directory the trained model along with the model code exist\n",
    "bm_path =  '../downloads/models/smplx/SMPLX_FEMALE.npz'#'PATH_TO_SMPLX_model.npz'  obtain from https://smpl-x.is.tue.mpg.de/downloads"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found Trained Model: ../downloads/vposer_v1_0/snapshots/TR00_E096.pt\n"
     ]
    }
   ],
   "source": [
    "from human_body_prior.body_model.body_model_vposer import BodyModelWithPoser\n",
    "\n",
    "\n",
    "bm = BodyModelWithPoser(bm_path=bm_path, batch_size=1, poser_type='vposer', smpl_exp_dir=expr_dir).to('cuda')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the above snippet, *bm* is a BodyModel isntance where the body pose is not represented by body_pose anymore, \n",
    "but with body_poZ that is the latent space of respective VPoser model. So in any optimization task that involves a human body\n",
    "you can use bm.body_poZ as the free variable and as a prior put a L2 norm on this vriable to keep it close to the mean of a Normal. Eventually, you can weight this term to choose between data and prior term."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "poZ_body torch.Size([1, 32])\n",
      "pose_body torch.Size([1, 63])\n"
     ]
    }
   ],
   "source": [
    "print('poZ_body', bm.poZ_body.shape)\n",
    "print('pose_body', bm.pose_body.shape)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can take a look at notebooks/vposer_sampling.ipynb to learn how to sample and visualize vposer novel poses."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
